/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package db.orm;

import java.lang.reflect.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Romms
 */
public class BeansGenerator {

    public static BeansGenerator instance;

    public static BeansGenerator getInstance(){
        if(instance==null){
            return new BeansGenerator();
        }else{
            return instance;
        }
    }

    private BeansGenerator(){
        
    }

    private final String SET_PREFIX="set";

    public Class getBeanKind() {
        return beanKind;
    }

    public void setBeanKind(Class beanKind) {
        this.beanKind = beanKind;
    }

    public ResultSet getQueryResult() {
        return queryResult;
    }

    public void setQueryResult(ResultSet queryResult) {
        this.queryResult = queryResult;
    }

    private Class beanKind;
    private ResultSet queryResult;

    private Object generateBean(ResultSet queryResult, Class beanKind ) throws ORMException, SQLException{
        this.setBeanKind(beanKind);
        this.setQueryResult(queryResult);
        return getBeanFrom();
    }

    private Object getBeanFrom() throws ORMException{
        Field[] listOFields = this.getBeanKind().getDeclaredFields();
        try{
            Object bean = beanKind.newInstance();
            for(Field field : listOFields){
                    Object fieldValue = this.getQueryResult().getObject(field.getName());
                    Method method = this.getBeanKind().getMethod(SET_PREFIX + firstLetterToCapital(field.getName()), field.getType());
                    method.invoke(bean, fieldValue);
             }
            return bean;
        } catch (NoSuchMethodException exception) {
            throw new ORMException(exception.getMessage(),exception);
        } catch (SecurityException exception) {
            throw new ORMException(exception.getMessage(),exception);
        }catch (IllegalArgumentException exception) {
            throw new ORMException(exception.getMessage(), exception);
        } catch (InvocationTargetException exception) {
            throw new ORMException(exception.getMessage(), exception);
        } catch (InstantiationException exception) {
            throw new ORMException(exception.getMessage(), exception);
        } catch (IllegalAccessException exception) {
            throw new ORMException(exception.getMessage(), exception);
        } catch (SQLException exception) {
            throw new ORMException(exception.getMessage(), exception);
        }
    }

    private String firstLetterToCapital(String toConvert){
        return toConvert.substring(0,1).toUpperCase() + toConvert.substring(1);
    }

    public Object generateSingleBean(ResultSet queryResult, Class beanKind)throws ORMException, SQLException{
        this.moveQueryResultToBegin(queryResult);
        return generateBean(queryResult, beanKind);
    }

    public ArrayList generateListOfBeans(ResultSet queryResult, Class beanKind){
        ArrayList<Object> listOfBeans = new ArrayList();
        try {
            while (queryResult.next()) {
                    listOfBeans.add(generateBean(queryResult, beanKind));
            }
        }catch (ORMException ex) {
            Logger.getLogger(BeansGenerator.class.getName()).log(Level.SEVERE, null, ex);
        }
            catch (SQLException ex) {
            Logger.getLogger(BeansGenerator.class.getName()).log(Level.SEVERE, null, ex);
        }
        return listOfBeans;

    }

     public void moveQueryResultToBegin(ResultSet queryResult) throws SQLException{
        queryResult.first();
    }
}
